package cn.signalpha.modules.com.controller.seller;

import cn.hutool.core.date.DateUtil;
import cn.signalpha.common.constant.AppConstant;
import cn.signalpha.common.utils.Arith;
import cn.signalpha.core.boot.ctrl.BaseController;
import cn.signalpha.core.mp.support.Condition;
import cn.signalpha.core.mp.support.Query;
import cn.signalpha.core.tool.api.R;
import cn.signalpha.core.tool.support.Kv;
import cn.signalpha.core.tool.utils.CollectionUtil;
import cn.signalpha.core.tool.utils.Func;
import cn.signalpha.core.tool.utils.ObjectUtil;
import cn.signalpha.modules.com.service.UserService;
import cn.signalpha.modules.shop.entity.Goods;
import cn.signalpha.modules.shop.entity.Order;
import cn.signalpha.modules.shop.service.GoodsService;
import cn.signalpha.modules.shop.service.OrderService;
import cn.signalpha.modules.shop.service.SellerService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.util.*;

/**
 * 控制器
 *
 * @author signalpha
 */
@RestController
@AllArgsConstructor
@RequestMapping(AppConstant.APPLICATION_BASE_NAME + "/sys-seller/stats")
@Api(value = "统计接口", tags = "统计接口")
public class SpiStatsController extends BaseController {

	private final UserService userService;
	private final GoodsService goodsService;
	private final OrderService orderService;
	private final SellerService sellerService;

	@GetMapping("/user/count")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "会员统计", notes = "")
	public R<List<Map<String, Object>>> userCount() {
		List<Map<String, Object>> list = new LinkedList<>();
		List<Long> userIds = orderService.selectUserIdBySellerId(getUser().getUserId());
		if(CollectionUtil.isEmpty(userIds)){
			list.add(Kv.create().set("title", "会员数量").set("count", 0));
		}else{
			list.add(Kv.create().set("title", "会员数量").set("count", userService.countByParams(Kv.create().set("ids", Func.join(userIds)))));
		}
		return R.data(list);
	}

	@GetMapping("/order1/count")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "订单统计", notes = "")
	public R<List<Map<String, Object>>> order1Count() {
		Date now = new Date();
		Date beginTimeDay = DateUtil.beginOfDay(now);
		Date beginTimeMonth = DateUtil.beginOfMonth(now);
		Long sellerId = getUser().getUserId();
		List<Map<String, Object>> list = new LinkedList<>();
		list.add(Kv.create().set("title", "订单总金额").set("count", orderService.sumByParams(Kv.create().set("sellerId", sellerId).set("payStatus", 1))));
		list.add(Kv.create().set("title", "订单总数量").set("count", orderService.countByParams(Kv.create().set("sellerId", sellerId).set("payStatus", 1))));
		list.add(Kv.create().set("title", "今日订单金额").set("count", orderService.sumByParams(Kv.create().set("sellerId", sellerId).set("payStatus", 1).set("createTimeBegin", beginTimeDay).set("createTimeEnd", now))));
		list.add(Kv.create().set("title", "今日订单数量").set("count", orderService.countByParams(Kv.create().set("sellerId", sellerId).set("payStatus", 1).set("createTimeBegin", beginTimeDay).set("createTimeEnd", now))));
		list.add(Kv.create().set("title", "本月订单金额").set("count", orderService.sumByParams(Kv.create().set("sellerId", sellerId).set("payStatus", 1).set("createTimeBegin", beginTimeMonth).set("createTimeEnd", now))));
		list.add(Kv.create().set("title", "本月订单数量").set("count", orderService.countByParams(Kv.create().set("sellerId", sellerId).set("payStatus", 1).set("createTimeBegin", beginTimeMonth).set("createTimeEnd", now))));
		return R.data(list);
	}

	@GetMapping("/goods/count")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "商品统计", notes = "")
	public R<List<Map<String, Object>>> goodsCount() {
		Long sellerId = getUser().getUserId();
		List<Map<String, Object>> list = new LinkedList<>();
		list.add(Kv.create().set("title", "商品数量").set("count", goodsService.countByParams(Kv.create().set("sellerId", sellerId))));
		list.add(Kv.create().set("title", "上架中商品").set("count", goodsService.countByParams(Kv.create().set("sellerId", sellerId).set("status", 1))));
		list.add(Kv.create().set("title", "下架中商品").set("count", goodsService.countByParams(Kv.create().set("sellerId", sellerId).set("status", 0))));
		list.add(Kv.create().set("title", "待审核商品").set("count", goodsService.countByParams(Kv.create().set("sellerId", sellerId).set("status", -1))));
		list.add(Kv.create().set("title", "强制下架商品").set("count", goodsService.countByParams(Kv.create().set("sellerId", sellerId).set("status", -2))));
		list.add(Kv.create().set("title", "审核未通过商品").set("count", goodsService.countByParams(Kv.create().set("sellerId", sellerId).set("status", -3))));
		return R.data(list);
	}

	@GetMapping("/goods/top")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "商品销量TOP", notes = "")
	public R<IPage<Goods>> orderMoneyTrend(@ApiIgnore @RequestParam Map<String, Object> params, Query query) {
		Long sellerId = getUser().getUserId();
		IPage<Goods> goodsList = goodsService.page(Condition.getPage(query), Wrappers.<Goods>query().lambda()
			.select(Goods::getName, Goods::getSalesVolume).orderByDesc(Goods::getSalesVolume)
			.eq(Goods::getSellerId, sellerId)
			.apply(ObjectUtil.isNotEmpty(params.get("categoryId")), "FIND_IN_SET ('" + params.get("categoryId") + "',category_id)")
			.apply(ObjectUtil.isNotEmpty(params.get("sellerGoodsCategoryId")), "FIND_IN_SET ('" + params.get("sellerGoodsCategoryId") + "',seller_goods_category_id)")
		);
		return R.data(goodsList);
	}

	@GetMapping("/order/money/trend")
	@ApiOperationSupport(order = 50)
	@ApiOperation(value = "订单交易额趋势图", notes = "")
	public R<List<Map<String, Object>>> orderMoneyTrend() {
		Long sellerId = getUser().getUserId();
		QueryWrapper<Order> wrapper = Wrappers.query();
		wrapper.select("DATE_FORMAT(create_time, '%Y-%m-%d') as date, SUM(IFNULL(goods_price,0)) as amount");
		wrapper.lambda().eq(Order::getPayStatus, 1);
		wrapper.lambda().eq(Order::getSellerId, sellerId);
		wrapper.groupBy("date");
		wrapper.orderByDesc("date");
		wrapper.lambda().last("limit 7");
		return R.data(orderService.listMaps(wrapper));
	}

	@GetMapping("/order/aoq/trend")
	@ApiOperationSupport(order = 51)
	@ApiOperation(value = "订单客单量趋势图", notes = "")
	public R<List<Map<String, Object>>> orderAoqTrend() {
		List<Map<String, Object>> mapList = new ArrayList<>(7);

		Date date = new Date();
		long userNum = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date)).set("createTimeBegin", DateUtil.endOfDay(date)));
		double goodsNum = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date)).set("createTimeBegin", DateUtil.endOfDay(date)), "goods_num");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date)).set("amount", goodsNum > 0 ? Arith.div(goodsNum, userNum) : 0));

		Date date1 = DateUtil.offsetDay(date, -1);
		long userNum1 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date1)).set("createTimeBegin", DateUtil.endOfDay(date1)));
		double goodsNum1 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date1)).set("createTimeBegin", DateUtil.endOfDay(date1)), "goods_num");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date1)).set("amount", goodsNum1 > 0 ? Arith.div(goodsNum1, userNum1) : 0));

		Date date2 = DateUtil.offsetDay(date, -2);
		long userNum2 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date2)).set("createTimeBegin", DateUtil.endOfDay(date2)));
		double goodsNum2 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date2)).set("createTimeBegin", DateUtil.endOfDay(date2)), "goods_num");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date2)).set("amount", goodsNum2 > 0 ? Arith.div(goodsNum2, userNum2) : 0));

		Date date3 = DateUtil.offsetDay(date, -3);
		long userNum3 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date3)).set("createTimeBegin", DateUtil.endOfDay(date3)));
		double goodsNum3 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date3)).set("createTimeBegin", DateUtil.endOfDay(date3)), "goods_num");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date3)).set("amount", goodsNum3 > 0 ? Arith.div(goodsNum2, userNum3) : 0));

		Date date4 = DateUtil.offsetDay(date, -4);
		long userNum4 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date4)).set("createTimeBegin", DateUtil.endOfDay(date4)));
		double goodsNum4 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date4)).set("createTimeBegin", DateUtil.endOfDay(date4)), "goods_num");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date4)).set("amount", goodsNum4 > 0 ? Arith.div(goodsNum4, userNum4) : 0));

		Date date5 = DateUtil.offsetDay(date, -5);
		long userNum5 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date5)).set("createTimeBegin", DateUtil.endOfDay(date5)));
		double goodsNum5 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date5)).set("createTimeBegin", DateUtil.endOfDay(date5)), "goods_num");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date5)).set("amount", goodsNum5 > 0 ? Arith.div(goodsNum5, userNum5) : 0));

		Date date6 = DateUtil.offsetDay(date, -6);
		long userNum6 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date6)).set("createTimeBegin", DateUtil.endOfDay(date6)));
		double goodsNum6 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date6)).set("createTimeBegin", DateUtil.endOfDay(date6)), "goods_num");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date6)).set("amount", goodsNum6 > 0 ? Arith.div(goodsNum6, userNum6) : 0));
		return R.data(mapList);
	}

	@GetMapping("/order/aov/trend")
	@ApiOperationSupport(order = 51)
	@ApiOperation(value = "订单客单价趋势图", notes = "")
	public R<List<Map<String, Object>>> orderAovTrend() {
		List<Map<String, Object>> mapList = new ArrayList<>(7);

		Date date = new Date();
		long userNum = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date)).set("createTimeBegin", DateUtil.endOfDay(date)));
		double orderPrice = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date)).set("createTimeBegin", DateUtil.endOfDay(date)), "goods_price");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date)).set("amount", orderPrice > 0 ? Arith.div(orderPrice, userNum) : 0));

		Date date1 = DateUtil.offsetDay(date, -1);
		long userNum1 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date1)).set("createTimeBegin", DateUtil.endOfDay(date1)));
		double orderPrice1 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date1)).set("createTimeBegin", DateUtil.endOfDay(date1)), "goods_price");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date1)).set("amount", orderPrice1 > 0 ? Arith.div(orderPrice1, userNum1) : 0));

		Date date2 = DateUtil.offsetDay(date, -2);
		long userNum2 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date2)).set("createTimeBegin", DateUtil.endOfDay(date2)));
		double orderPrice2 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date2)).set("createTimeBegin", DateUtil.endOfDay(date2)), "goods_price");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date2)).set("amount", orderPrice2 > 0 ? Arith.div(orderPrice2, userNum2) : 0));

		Date date3 = DateUtil.offsetDay(date, -3);
		long userNum3 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date3)).set("createTimeBegin", DateUtil.endOfDay(date3)));
		double orderPrice3 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date3)).set("createTimeBegin", DateUtil.endOfDay(date3)), "goods_price");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date3)).set("amount", orderPrice3 > 0 ? Arith.div(orderPrice2, userNum3) : 0));

		Date date4 = DateUtil.offsetDay(date, -4);
		long userNum4 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date4)).set("createTimeBegin", DateUtil.endOfDay(date4)));
		double orderPrice4 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date4)).set("createTimeBegin", DateUtil.endOfDay(date4)), "goods_price");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date4)).set("amount", orderPrice4 > 0 ? Arith.div(orderPrice4, userNum4) : 0));

		Date date5 = DateUtil.offsetDay(date, -5);
		long userNum5 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date5)).set("createTimeBegin", DateUtil.endOfDay(date5)));
		double orderPrice5 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date5)).set("createTimeBegin", DateUtil.endOfDay(date5)), "goods_price");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date5)).set("amount", orderPrice5 > 0 ? Arith.div(orderPrice5, userNum5) : 0));

		Date date6 = DateUtil.offsetDay(date, -6);
		long userNum6 = orderService.countUserNum(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date6)).set("createTimeBegin", DateUtil.endOfDay(date6)));
		double orderPrice6 = orderService.sumByParams(Kv.create().set("payStatus", 1).set("createTimeBegin", DateUtil.beginOfDay(date6)).set("createTimeBegin", DateUtil.endOfDay(date6)), "goods_price");
		mapList.add(Kv.create().set("date", DateUtil.formatDate(date6)).set("amount", orderPrice6 > 0 ? Arith.div(orderPrice6, userNum6) : 0));
		return R.data(mapList);
	}

}
